﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace CGeers.Wcf.Services.Preprocesslanguage
{
    public class NgramN
    {
        public static Dictionary<string, Dictionary<string, double>> P1 = new Dictionary<string, Dictionary<string, double>>();
        public static Dictionary<string, Dictionary<string, int>> w1 = new Dictionary<string, Dictionary<string, int>>();
        public static Dictionary<string, Dictionary<string, int>> w2 = new Dictionary<string, Dictionary<string, int>>();
        public static Dictionary<string, Dictionary<string, int>> w3 = new Dictionary<string, Dictionary<string, int>>();


        public Dictionary<string, double> process(string input)
        {
            Dictionary<string,double> rs=new Dictionary<string,double>();
            Dictionary<string,double> rsTemp = null;
            string[] words = input.Split(' ');
            string wordToUs="";
            if (words.Length != 0)
            {
                wordToUs=CGeers.Wcf.Services.Utils.processUtils.ConvertToUnSign(words[0]);
                if (P1.ContainsKey(wordToUs))
                {
                    rs = P1[wordToUs];
                }
                else
                {
                    rs.Add(words[0], 1 / 100);
                }
                if (words.Length >= 2)
                {
                    wordToUs = CGeers.Wcf.Services.Utils.processUtils.ConvertToUnSign(words[1]);
                    if (w1.ContainsKey(wordToUs))
                    {
                        rsTemp = new Dictionary<string, double>();
                        foreach (KeyValuePair<string, double> item in rs)
                        {
                            foreach (KeyValuePair<string, int> i in w1[wordToUs])
                            {
                                rsTemp.Add(item.Key + " " + i.Key,item.Value*P(i.Key, item.Key + " " + i.Key, 1));
                            }
                        }
                        rs = getKqForCount(rsTemp, 5);
                    }
                    else
                    {
                        rsTemp = new Dictionary<string, double>();
                        foreach (KeyValuePair<string, double> item in rs)
                        {
                            rsTemp.Add(item.Key + " " + words[1], item.Value / 100);
                        }
                        rs = rsTemp;
                    }
                    if (words.Length >= 3)
                    {
                        wordToUs = CGeers.Wcf.Services.Utils.processUtils.ConvertToUnSign(words[2]);
                        if (w1.ContainsKey(wordToUs))
                        {
                            rsTemp = new Dictionary<string, double>();
                            foreach (KeyValuePair<string, double> item in rs)
                            {
                                foreach (KeyValuePair<string, int> i in w1[wordToUs])
                                {
                                    rsTemp.Add(item.Key + " " + i.Key, item.Value * P(i.Key, item.Key + " " + i.Key, 2));
                                }
                            }
                            rs = getKqForCount(rsTemp, 5);
                        }
                        else
                        {
                            rsTemp = new Dictionary<string, double>();
                            foreach (KeyValuePair<string, double> item in rs)
                            {
                                rsTemp.Add(item.Key + " " + words[2], item.Value / 100);
                            }
                            rs = rsTemp;
                        }
                        if (words.Length > 3)
                        {
                            for (int j = 1; j < words.Length-2; j++)
                            {
                                wordToUs = CGeers.Wcf.Services.Utils.processUtils.ConvertToUnSign(words[j + 2]);
                                if (w1.ContainsKey(wordToUs))
                                {
                                    rsTemp = new Dictionary<string, double>();
                                    foreach (KeyValuePair<string, double> item in rs)
                                    {
                                        foreach (KeyValuePair<string, int> i in w1[wordToUs])
                                        {
                                            rsTemp.Add(item.Key + " " + i.Key, item.Value * P(i.Key, item.Key + " " + i.Key, 2));
                                        }
                                    }
                                    rs = getKqForCount(rsTemp, 5);
                                }
                                else
                                {
                                    rsTemp = new Dictionary<string, double>();
                                    foreach (KeyValuePair<string, double> item in rs)
                                    {
                                        rsTemp.Add(item.Key + " " + words[j+2], item.Value / 100);
                                    }
                                    rs = rsTemp;
                                }
                            }
                        }
                    }
                }
            }
            return rs;
        }

        public double P(string wo1, string str,int i)
        {
            double rs = 0;
            string temp="";
            string[] wo = str.Split(' ');
            if (i == 1)
            {
                temp =wo[wo.Length-2]+" "+wo1;
                if (w2.ContainsKey(CGeers.Wcf.Services.Utils.processUtils.ConvertToUnSign(temp)))
                {
                    if (w2[CGeers.Wcf.Services.Utils.processUtils.ConvertToUnSign(temp)].ContainsKey(temp))
                    {
                        rs = w2[CGeers.Wcf.Services.Utils.processUtils.ConvertToUnSign(temp)][temp] * 1.0 / w1[CGeers.Wcf.Services.Utils.processUtils.ConvertToUnSign(wo1)][wo1];
                    }
                }
            }
            if (i == 2)
            {
                temp = wo[wo.Length - 3] + " " + wo[wo.Length - 2] + " " + wo1;
                if (w3.ContainsKey(CGeers.Wcf.Services.Utils.processUtils.ConvertToUnSign(temp)))
                {
                    if (w3[CGeers.Wcf.Services.Utils.processUtils.ConvertToUnSign(temp)].ContainsKey(temp))
                    {
                        rs = w3[CGeers.Wcf.Services.Utils.processUtils.ConvertToUnSign(temp)][temp] * 1.0 / w1[CGeers.Wcf.Services.Utils.processUtils.ConvertToUnSign(wo1)][wo1];
                    }
                }
            }
            return rs;
        }

        public string getKq(Dictionary<string, double> kq)
        {
            try
            {
                double max = kq.Max(kvp => kvp.Value);
                return kq.Where(kvp => kvp.Value == max).Select(kvp => kvp.Key).First();
            }
            catch (Exception)
            {
                return null;
            }
        }
        public Dictionary<string, double> getKqForCount(Dictionary<string, double> dict, int count)
        {
            var items = from pair in dict
                        orderby pair.Value descending
                        select pair;
            Dictionary<string, double> kq = new Dictionary<string, double>();
            foreach (KeyValuePair<string, double> pair in items)
            {
                if (count == 0)
                    return kq;
                count--;
                kq.Add(pair.Key, pair.Value);
            }
            return kq;
        }
        public static bool readData(string path1, string path2, string path3, string path4)
        {
            try
            {
                StreamReader sr = new StreamReader(path1);
                Dictionary<string, double> pp;
                string str;
                while ((str = sr.ReadLine()) != null)
                {
                    string[] ppp = str.Split(':');
                    string[] pppp = ppp[1].Split(';');
                    pp = new Dictionary<string, double>();
                    foreach (string s in pppp)
                    {
                        string[] ppppp = s.Split('-');
                        pp.Add(ppppp[0], double.Parse(ppppp[1]));
                    }
                    P1.Add(ppp[0], pp);
                }
                sr.Close();
                Dictionary<string, int> pp1;
                sr = new StreamReader(path2);
                while ((str = sr.ReadLine()) != null)
                {
                    string[] ppp = str.Split(':');
                    string[] pppp = ppp[1].Split(';');
                    pp1 = new Dictionary<string, int>();
                    foreach (string s in pppp)
                    {
                        string[] ppppp = s.Split('-');
                        pp1.Add(ppppp[0], int.Parse(ppppp[1]));
                    }
                    w1.Add(ppp[0], pp1);
                }
                sr.Close();
                sr = new StreamReader(path3);
                while ((str = sr.ReadLine()) != null)
                {
                    string[] ppp = str.Split(':');
                    string[] pppp = ppp[1].Split(';');
                    pp1 = new Dictionary<string, int>();
                    foreach (string s in pppp)
                    {
                        string[] ppppp = s.Split('-');
                        pp1.Add(ppppp[0], int.Parse(ppppp[1]));
                    }
                    w2.Add(ppp[0], pp1);
                }
                sr.Close();
                sr = new StreamReader(path4);
                while ((str = sr.ReadLine()) != null)
                {
                    string[] ppp = str.Split(':');
                    string[] pppp = ppp[1].Split(';');
                    pp1 = new Dictionary<string, int>();
                    foreach (string s in pppp)
                    {
                        string[] ppppp = s.Split('-');
                        pp1.Add(ppppp[0], int.Parse(ppppp[1]));
                    }
                    w3.Add(ppp[0], pp1);
                }
                sr.Close();
                return true;
            }
            catch (Exception)
            {
                return false;
            }

        }
    }
}
